Passed
Push — master ( 4d5c01...5ac246 )
by EMP
01:10
created

main.js ➔ TabState   A

Complexity

Conditions 5

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 5
dl 0
loc 6
rs 9.3333
c 0
b 0
f 0
1
"use strict";
2
3
sodium.ready.then(function() {
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
4
5
const ae = new AllEars(function(ok) {
1 ignored issue
show
Bug introduced by
The variable AllEars seems to be never declared. If this is a global, consider adding a /** global: AllEars */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
6
	if (ok) {
7
		const greeting = localStorage.greeting;
1 ignored issue
show
Bug introduced by
The variable localStorage seems to be never declared. If this is a global, consider adding a /** global: localStorage */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
8
		if (greeting) {
9
			document.getElementById("greeting").textContent = greeting;
10
			document.getElementById("txt_pg").value = greeting;
11
		}
12
13
		document.getElementById("txt_skey").style.background = "#466";
14
		document.getElementById("txt_skey").maxLength = "64";
15
	} else {
16
		console.log("Failed to load All-Ears");
17
	}
18
});
19
20
function TabState(cur, max, btnDele, btnUpdt) {
21
	this.cur = cur;
22
	this.max = max;
23
	this.btnDele = btnDele;
24
	this.btnUpdt = btnUpdt;
25
}
26
27
const tabs = [
28
	new TabState(0, 0, false, true), // Inbox
29
	new TabState(0, 0, false, true), // Outbx
30
	new TabState(0, 2, true, false), // Write
31
	new TabState(0, 2, false, false), // Notes
32
	new TabState(0, 3, false, true) // Tools
33
];
34
35
let showHeaders = false;
36
37
let tab = 0;
38
const TAB_INBOX = 0;
39
const TAB_DRBOX = 1;
40
const TAB_WRITE = 2;
41
const TAB_NOTES = 3;
42
const TAB_TOOLS = 4;
43
44
// Helper functions
45
function getCountryName(countryCode) {
46
	const opts = document.getElementById("gatekeeper_country");
47
48
	for (let i = 0; i < opts.length; i++) {
49
		if (opts[i].value === countryCode) {
50
			return opts[i].textContent;
51
		}
52
	}
53
54
	return "Unknown countrycode: " + countryCode;
55
}
56
57
function getCountryFlag(countryCode) {
58
	return sodium.to_string(new Uint8Array([
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
59
		240, 159, 135, 166 + countryCode.codePointAt(0) - 65,
60
		240, 159, 135, 166 + countryCode.codePointAt(1) - 65
61
	]));
62
}
63
64
function getMsgId(num) {
65
	let i;
66
	if (ae.GetExtMsgHeaders(num).toLowerCase().slice(0, 11) === "message-id:") {
67
		i = 0;
68
	} else {
69
		i = ae.GetExtMsgHeaders(num).toLowerCase().indexOf("\nmessage-id:");
70
		if (i < 1) return "ERR";
71
		i++;
72
	}
73
74
	const x = ae.GetExtMsgHeaders(num).slice(i + 11).trim();
75
	if (x[0] !== "<") return "ERR2";
76
	return x.slice(1, x.indexOf(">"));
77
}
78
79
function clearDisplay() {
80
	let el = document.getElementById("midright").getElementsByTagName("img");
81
	if (el.length !== 1) el = document.getElementById("midright").getElementsByTagName("audio");
82
	if (el.length !== 1) el = document.getElementById("midright").getElementsByTagName("video");
83
	if (el.length !== 1) el = document.getElementById("midright").getElementsByTagName("embed");
84
	if (el.length !== 1) el = document.getElementById("midright").getElementsByTagName("iframe");
85
	if (el.length !== 1) return;
86
87
	URL.revokeObjectURL(el[0].src);
1 ignored issue
show
Bug introduced by
The variable URL seems to be never declared. If this is a global, consider adding a /** global: URL */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
88
	el[0].remove();
89
}
90
91
function displayFile(num) {
92
	clearDisplay();
93
94
	document.getElementById("midright").scroll(0, 0);
95
	document.getElementById("btn_reply").disabled = true;
96
	document.getElementById("btn_mdele").disabled = true;
97
98
	document.getElementById("midright").children[0].hidden = true;
99
	document.getElementById("midright").children[1].textContent = ae.GetUplMsgTitle(num);
100
101
	switch (ae.GetUplMsgType(num)) {
102
		case "text": {
103
			document.getElementById("midright").children[2].hidden = false;
104
			document.getElementById("midright").children[2].textContent = sodium.to_string(ae.GetUplMsgBody(num));
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
105
		break;}
106
107
		case "image": {
108
			document.getElementById("midright").children[2].hidden = true;
109
			const img = document.createElement("img");
110
			img.src = URL.createObjectURL(new Blob([ae.GetUplMsgBody(num).buffer]));
2 ignored issues
show
Bug introduced by
The variable Blob seems to be never declared. If this is a global, consider adding a /** global: Blob */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Bug introduced by
The variable URL seems to be never declared. If this is a global, consider adding a /** global: URL */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
111
			document.getElementById("midright").appendChild(img);
112
113
			img.onclick = function() {
114
				if (!document.fullscreen)
115
					img.requestFullscreen();
116
				else
117
					document.exitFullscreen();
118
			};
119
		break;}
120
121
		case "audio": {
122
			document.getElementById("midright").children[2].hidden = true;
123
			const el = document.createElement("audio");
124
			el.controls = "controls";
125
			el.src = URL.createObjectURL(new Blob([ae.GetUplMsgBody(num).buffer]));
126
			document.getElementById("midright").appendChild(el);
127
		break;}
128
129
		case "video": {
130
			document.getElementById("midright").children[2].hidden = true;
131
			const el = document.createElement("video");
132
			el.controls = "controls";
133
			el.src = URL.createObjectURL(new Blob([ae.GetUplMsgBody(num).buffer]));
134
			document.getElementById("midright").appendChild(el);
135
		break;}
136
137
		case "pdf": {
138
			document.getElementById("midright").children[2].hidden = true;
139
			const el = document.createElement("embed");
140
			el.type = "application/pdf";
141
			el.src = URL.createObjectURL(new Blob([ae.GetUplMsgBody(num).buffer], {type: "application/pdf"}));
142
			document.getElementById("midright").appendChild(el);
143
		break;}
144
145
		case "html": {
146
			document.getElementById("midright").children[2].hidden = true;
147
			const el = document.createElement("iframe");
148
			el.allow = "";
149
			el.sandbox = "";
150
			el.csp = "base-uri 'none'; child-src 'none'; connect-src 'none'; default-src 'none'; font-src 'none'; form-action 'none'; frame-ancestors 'none'; frame-src 'none'; img-src 'none'; manifest-src 'none'; media-src 'none'; object-src 'none'; script-src 'none'; style-src 'none'; worker-src 'none';";
151
			el.srcdoc = sodium.to_string(ae.GetUplMsgBody(num).buffer);
152
			document.getElementById("midright").appendChild(el);
153
		break;}
154
	}
155
}
156
157
function displayMsg(isInt, num) {
158
	clearDisplay();
159
160
	document.getElementById("midright").scroll(0, 0);
161
162
	const ts = isInt? ae.GetIntMsgTime(num) : ae.GetExtMsgTime(num);
163
164
	document.getElementById("btn_reply").disabled = false;
165
	document.getElementById("btn_reply").onclick = function() {
166
		document.getElementById("write_recv").value = isInt? ae.GetIntMsgFrom(num) : ae.GetExtMsgFrom(num);
167
		document.getElementById("write_subj").value = "Re: " + (isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num));
168
		document.getElementById("write_rply").textContent = (isInt? "" : getMsgId(num));
169
		document.getElementById("btn_write").click();
170
		document.getElementById("div_write_1").hidden = false;
171
		document.getElementById("div_write_2").hidden = true;
172
		document.getElementById("write_body").focus();
173
		for (const opt of document.getElementById("write_from").options) {
174
			if (opt.value === (isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num))) {
175
				opt.selected = true;
176
			}
177
		}
178
	};
179
180
	document.getElementById("btn_mdele").disabled = false;
181
	document.getElementById("btn_mdele").onclick = function() {
182
		this.blur();
183
184
		ae.Message_Delete(isInt? ae.GetIntMsgIdHex(num) : ae.GetExtMsgIdHex(num), function(success) {
185
			if (!success) console.log("Failed delete");
186
		});
187
	};
188
189
	document.getElementById("midright").children[0].hidden = false;
190
	document.getElementById("midright").children[2].hidden = false;
191
192
	if (isInt) {
193
		document.getElementById("midright").children[1].textContent = ae.GetIntMsgTitle(num);
194
		document.getElementById("midright").children[2].textContent = ae.GetIntMsgBody(num);
195
	} else {
196
		document.getElementById("midright").children[2].innerHTML = "";
197
198
		const headers = document.createElement("p");
199
		headers.textContent = ae.GetExtMsgHeaders(num);
200
		headers.className = "mono";
201
		headers.hidden = !showHeaders;
202
		document.getElementById("midright").children[2].appendChild(headers);
203
204
		const body = document.createElement("p");
205
		body.textContent = ae.GetExtMsgBody(num);
206
		document.getElementById("midright").children[2].appendChild(body);
207
208
		document.getElementById("midright").children[1].textContent = ae.GetExtMsgTitle(num);
209
		document.getElementById("midright").children[1].onclick = function() {showHeaders = !showHeaders; headers.hidden = !showHeaders;};
210
		document.getElementById("midright").children[1].style.cursor = "pointer";
211
	}
212
213
	document.getElementById("readmsg_to").textContent = isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num);
214
215
	const tzOs = new Date().getTimezoneOffset();
216
	const tz = ((tzOs < 0) ? "+" : "-") + Math.floor(tzOs / -60).toString().padStart(2, "0") + (tzOs % 60 * -1).toString().padStart(2, "0");
217
	document.getElementById("readmsg_date").children[0].textContent = new Date((ts * 1000) + (tzOs * -60000)).toISOString().slice(0, 19).replace("T", " ") + " " + tz;
218
219
	if (!isInt) {
220
		document.getElementById("readmsg_ip").hidden = false;
221
		document.getElementById("readmsg_country").hidden = false;
222
		document.getElementById("readmsg_tls").hidden = false;
223
		document.getElementById("readmsg_greet").hidden = false;
224
		document.getElementById("readmsg_timing").hidden = false;
225
		document.getElementById("readmsg_envfrom").hidden = false;
226
227
		const cc = ae.GetExtMsgCountry(num);
228
229
		document.getElementById("readmsg_ip").children[0].textContent = ae.GetExtMsgIp(num);
230
		document.getElementById("readmsg_country").textContent = getCountryFlag(cc) + " " + getCountryName(cc);
231
		document.getElementById("readmsg_tls").children[0].textContent = ae.GetExtMsgTLS(num);
232
		document.getElementById("readmsg_greet").children[0].textContent = ae.GetExtMsgGreet(num);
233
		document.getElementById("readmsg_envfrom").textContent = ae.GetExtMsgFrom(num);
234
235
		let flagText = "";
236
		if (!ae.GetExtMsgFlagVPad(num)) flagText += "<abbr title=\"Invalid padding\">PAD</abbr> ";
237
		if (!ae.GetExtMsgFlagVSig(num)) flagText += "<abbr title=\"Invalid signature\">SIG</abbr> ";
238
		if (!ae.GetExtMsgFlagPExt(num)) flagText += "<abbr title=\"The sender did not use the Extended (ESMTP) protocol\">SMTP</abbr> ";
239
		if (!ae.GetExtMsgFlagQuit(num)) flagText += "<abbr title=\"The sender did not issue the required QUIT command\">QUIT</abbr> ";
240
		if (ae.GetExtMsgFlagRare(num)) flagText += "<abbr title=\"The sender issued unusual command(s)\">RARE</abbr> ";
241
		if (ae.GetExtMsgFlagFail(num)) flagText += "<abbr title=\"The sender issued invalid command(s)\">FAIL</abbr> ";
242
		if (ae.GetExtMsgFlagPErr(num)) flagText += "<abbr title=\"The sender violated the protocol\">PROT</abbr> ";
243
		document.getElementById("readmsg_flags").children[0].innerHTML = flagText.trim();
244
	} else {
245
		document.getElementById("readmsg_ip").hidden = true;
246
		document.getElementById("readmsg_country").hidden = true;
247
		document.getElementById("readmsg_tls").hidden = true;
248
		document.getElementById("readmsg_greet").hidden = true;
249
		document.getElementById("readmsg_timing").hidden = true;
250
		document.getElementById("readmsg_envfrom").hidden = true;
251
252
		let symbol = "<span title=\"Invalid level\">&#x26a0;</span>";
253
		if (ae.GetIntMsgFrom(num) === "system") {if (ae.GetIntMsgLevel(num) === 3) symbol = "<span title=\"System\">&#x1f162;</span>";} // S (System)
254
		else if (ae.GetIntMsgLevel(num) === 0) symbol = "<span title=\"Level 0 User\">&#x1f10c;</span>"; // 0
255
		else if (ae.GetIntMsgLevel(num) === 1) symbol = "<span title=\"Level 1 User\">&#x278a;</span>"; // 1
256
		else if (ae.GetIntMsgLevel(num) === 2) symbol = "<span title=\"Level 2 User\">&#x278b;</span>"; // 2
257
		else if (ae.GetIntMsgLevel(num) === 3) symbol = "<span title=\"Administrator\">&#x1f150;</span>"; // A (Admin)
258
		document.getElementById("readmsg_from").innerHTML = symbol + " " + ae.GetIntMsgFrom(num);
259
260
		let flagText = "";
261
		if (!ae.GetIntMsgFlagVPad(num)) flagText += "<abbr title=\"Invalid padding\">PAD</abbr> ";
262
		if (!ae.GetIntMsgFlagVSig(num)) flagText += "<abbr title=\"Invalid signature\">SIG</abbr> ";
263
		document.getElementById("readmsg_flags").children[0].innerHTML = flagText.trim();
264
	}
265
}
266
267
// Interface
268
function addMsg(isInt, i) {
269
	const row = document.getElementById("tbl_inbox").insertRow(-1);
270
	const cellTime = row.insertCell(-1);
271
	const cellSubj = row.insertCell(-1);
272
	const cellSnd1 = row.insertCell(-1);
273
	const cellSnd2 = row.insertCell(-1);
274
275
	const ts = isInt? ae.GetIntMsgTime(i) : ae.GetExtMsgTime(i);
276
	cellTime.setAttribute("data-ts", ts);
277
	cellTime.textContent = new Date((ts * 1000) + (new Date().getTimezoneOffset() * -60000)).toISOString().slice(0, 10);
278
279
	cellSubj.textContent = isInt? ae.GetIntMsgTitle(i) : ae.GetExtMsgTitle(i);
280
281
	if (isInt) {
282
		cellSnd1.textContent = ae.GetIntMsgFrom(i);
283
		cellSnd1.className = (ae.GetIntMsgFrom(i).length === 16) ? "mono" : "";
284
	} else {
285
		const from1 = ae.GetExtMsgFrom(i);
286
		const from2 = from1.substring(from1.indexOf("@") + 1);
287
		const cc = ae.GetExtMsgCountry(i);
288
289
		cellSnd1.textContent = from1.substring(0, from1.indexOf("@"));
290
291
		const flag = document.createElement("abbr");
292
		flag.textContent = getCountryFlag(cc);
293
		flag.title = getCountryName(cc);
294
		cellSnd2.appendChild(flag);
295
296
		const fromText = document.createElement("span");
297
		fromText.textContent = " " + from2;
298
		cellSnd2.appendChild(fromText);
299
	}
300
301
	row.onclick = function() {
302
		displayMsg(isInt, i);
303
	};
304
}
305
306
function getRowsPerPage() {
307
	const tbl = document.getElementById("tbl_inbox");
308
	tbl.innerHTML = "";
309
	const row = tbl.insertRow(-1);
310
	const cell = row.insertCell(-1);
311
	cell.textContent = "0";
312
313
	const rowsPerPage = Math.floor(getComputedStyle(document.getElementById("div_inbox")).height.replace("px", "") / getComputedStyle(document.querySelector("#tbl_inbox > tbody > tr:first-child")).height.replace("px", "")) - 1; // -1 allows space for 'load more'
314
	tbl.innerHTML = "";
315
	return rowsPerPage;
316
}
317
318
function addMessages() {
319
	const rowsPerPage = getRowsPerPage();
320
	let skipMsgs = rowsPerPage * tabs[TAB_INBOX].cur;
321
322
	const maxExt = ae.GetExtMsgCount();
323
	const maxInt = ae.GetIntMsgCount();
324
325
	tabs[TAB_INBOX].max = Math.floor((maxExt + maxInt) / rowsPerPage);
326
327
	let numExt = 0;
328
	let numInt = 0;
329
	let numAdd = 0;
330
331
	while (numAdd < rowsPerPage) {
332
		const tsInt = (numInt < maxInt) ? ae.GetIntMsgTime(numInt) : -1;
333
		const tsExt = (numExt < maxExt) ? ae.GetExtMsgTime(numExt) : -1;
334
		if (tsInt === -1 && tsExt === -1) break;
335
336
		if (tsInt !== -1 && (tsExt === -1 || tsInt > tsExt)) {
337
			if (skipMsgs > 0) skipMsgs--; else {addMsg(true, numInt); numAdd++;}
338
			numInt++;
339
		} else if (tsExt !== -1) {
340
			if (skipMsgs > 0) skipMsgs--; else {addMsg(false, numExt); numAdd++;}
341
			numExt++;
342
		}
343
	}
344
345
	if (ae.GetReadyMsgBytes() < ae.GetTotalMsgBytes()) {
346
		const inbox = document.getElementById("tbl_inbox");
347
		const row = inbox.insertRow(-1);
348
		const cell = row.insertCell(-1);
349
		cell.textContent = "Load more (" + (ae.GetTotalMsgBytes() - ae.GetReadyMsgBytes()) / 1024 + " KiB left)";
350
351
		row.onclick = function() {
352
			this.onclick = "";
353
354
			ae.Message_Browse(false, false, function(successBrowse) {
355
				document.getElementById("tbl_inbox").style.opacity = 1;
356
357
				if (successBrowse) {
358
					addMessages();
359
					addUploads();
360
					addSent();
361
					if (tabs[tab].cur < tabs[tab].max) document.getElementById("btn_rght").disabled = false;
362
				}
363
			});
364
		};
365
	}
366
}
367
368
function addUploads() {
369
	const tbl = document.getElementById("tbd_uploads");
370
	tbl.innerHTML = "";
371
372
	for (let i = 0; i < ae.GetUplMsgCount(); i++) {
373
		const row = tbl.insertRow(-1);
374
		let cell;
375
		cell = row.insertCell(-1); cell.textContent = new Date(ae.GetUplMsgTime(i) * 1000).toISOString().slice(0, 10);
376
377
		cell = row.insertCell(-1); cell.textContent = ae.GetUplMsgTitle(i);
378
		cell.onclick = function() {displayFile(this.parentElement.rowIndex - 1);};
379
380
		cell = row.insertCell(-1); cell.textContent = (ae.GetUplMsgBytes(i) / 1024).toFixed(1);
381
382
		cell = row.insertCell(-1);
383
		if (ae.GetUplMsgIdHex(i)) {
384
			cell.innerHTML = "<button data-msgid=\"" + ae.GetUplMsgIdHex(i) + "\" type=\"button\">X</button>";
385
386
			cell.children[0].onclick = function() {
387
				const tr = this.parentElement.parentElement;
388
				ae.Message_Delete(this.getAttribute("data-msgid"), function(success) {
389
					if (success) tr.remove();
390
				});
391
			};
392
		}
393
	}
394
}
395
396
function displayOutMsg(num) {
397
	clearDisplay();
398
	document.getElementById("midright").scroll(0, 0);
399
400
	document.getElementById("btn_reply").disabled = true;
401
	document.getElementById("btn_mdele").disabled = false;
402
	document.getElementById("btn_mdele").onclick = function() {
403
		this.blur();
404
		ae.Message_Delete(ae.GetOutMsgIdHex(num), function(success) {
405
			if (!success) console.log("Failed delete");
406
		});
407
	};
408
409
	document.getElementById("midright").children[0].hidden = false;
410
	document.getElementById("midright").children[2].hidden = false;
411
412
//	if (isInt) {
413
		document.getElementById("midright").children[1].textContent = ae.GetOutMsgSubj(num);
414
		document.getElementById("midright").children[2].textContent = ae.GetOutMsgBody(num);
415
//	} else {
416
//	}
417
418
	document.getElementById("readmsg_to").textContent = ae.GetOutMsgTo(num);
419
	document.getElementById("readmsg_envfrom").hidden = false;
420
	document.getElementById("readmsg_envfrom").textContent = ae.GetOutMsgFrom(num);
421
422
	const ts = ae.GetOutMsgTime(num);
423
	const tzOs = new Date().getTimezoneOffset();
424
	const tz = ((tzOs < 0) ? "+" : "-") + Math.floor(tzOs / -60).toString().padStart(2, "0") + (tzOs % 60 * -1).toString().padStart(2, "0");
425
	document.getElementById("readmsg_date").children[0].textContent = new Date((ts * 1000) + (tzOs * -60000)).toISOString().slice(0, 19).replace("T", " ") + " " + tz;
426
427
//	if (!isInt) {
428
		document.getElementById("readmsg_ip").hidden = false;
429
		document.getElementById("readmsg_country").hidden = false;
430
		document.getElementById("readmsg_tls").hidden = false;
431
		document.getElementById("readmsg_greet").hidden = false;
432
433
//		const cc = ae.GetExtMsgCountry(num);
434
435
		document.getElementById("readmsg_ip").children[0].textContent = ae.GetOutMsgIp(num);
436
//		document.getElementById("readmsg_country").textContent = getCountryFlag(cc) + " " + getCountryName(cc);
437
//		document.getElementById("readmsg_tls").children[0].textContent = ae.GetOutMsgTLS(num);
438
		document.getElementById("readmsg_greet").children[0].textContent = ae.GetOutMsgGreet(num);
439
//		document.getElementById("readmsg_envfrom").textContent = ae.GetExtMsgFrom(num);
440
//	} else {
441
//	}
442
}
443
444
function addSent() {
445
	const tbl = document.getElementById("tbl_drbox");
446
	tbl.innerHTML = "";
447
448
	for (let i = 0; i < ae.GetOutMsgCount(); i++) {
449
		const row = tbl.insertRow(-1);
450
		let cell;
451
452
		cell = row.insertCell(-1); cell.textContent = new Date(ae.GetOutMsgTime(i) * 1000).toISOString().slice(0, 10);
453
		cell = row.insertCell(-1); cell.textContent = ae.GetOutMsgSubj(i);
454
		row.onclick = function() {displayOutMsg(i);};
455
	}
456
}
457
458
function updateAddressCounts() {
459
	document.getElementById("limit_normal").textContent = (ae.GetAddressCountNormal() + "/" + ae.GetLimitNormalA(ae.GetUserLevel())).padStart(ae.GetLimitNormalA(ae.GetUserLevel()) > 9 ? 5 : 1);
460
	document.getElementById("limit_shield").textContent = (ae.GetAddressCountShield() + "/" + ae.GetLimitShieldA(ae.GetUserLevel())).padStart(ae.GetLimitShieldA(ae.GetUserLevel()) > 9 ? 5 : 1);
461
	document.getElementById("limit_total").textContent = ((ae.GetAddressCountNormal() + ae.GetAddressCountShield()) + "/" + ae.GetAddrPerUser()).padStart(5);
462
}
463
464
function adjustLevel(pubkey, level, c) {
465
	const fs = document.getElementById("fs_accs");
466
	fs.disabled = true;
467
468
	ae.Account_Update(pubkey, level, function(success) {
469
		fs.disabled = false;
470
471
		if (success) {
472
			c[4].textContent = level;
473
			c[5].children[0].disabled = (level === 3);
474
			c[6].children[0].disabled = (level === 0);
475
		}
476
	});
477
}
478
479
function addAccountToTable(i) {
480
	const tblAccs = document.getElementById("tbd_accs");
481
	const row = tblAccs.insertRow(-1);
482
	let cell;
483
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserPkHex(i);
484
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserSpace(i);
485
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserNAddr(i);
486
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserSAddr(i);
487
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserLevel(i);
488
489
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">+</button>";
490
	cell.children[0].onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(c[0].textContent, parseInt(c[4].textContent) + 1, c);};
491
	cell.children[0].disabled = (ae.Admin_GetUserLevel(i) === 3);
492
493
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">&minus;</button>";
494
	cell.children[0].onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(c[0].textContent, parseInt(c[4].textContent) - 1, c);};
495
	cell.children[0].disabled = (ae.Admin_GetUserLevel(i) === 0);
496
497
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">X</button>";
498
	cell.children[0].onclick = function() {
499
		const tr = this.parentElement.parentElement;
500
		ae.Account_Delete(tr.cells[0].textContent, function(success) {
501
			if (success) tr.remove();
502
		});
503
	};
504
}
505
506
function reloadAccount() {
507
	// Limits
508
	const tblLimits = document.getElementById("tbl_limits");
509
	if (ae.IsUserAdmin()) {
510
		for (let i = 0; i < 4; i++) {
511
			tblLimits.rows[i].cells[1].children[0].disabled = false;
512
			tblLimits.rows[i].cells[2].children[0].disabled = false;
513
			tblLimits.rows[i].cells[3].children[0].disabled = false;
514
515
			tblLimits.rows[i].cells[1].children[0].value = ae.GetLimitStorage(i) + 1;
516
			tblLimits.rows[i].cells[2].children[0].value = ae.GetLimitNormalA(i);
517
			tblLimits.rows[i].cells[3].children[0].value = ae.GetLimitShieldA(i);
518
		}
519
	} else {
520
		const lvl = ae.GetUserLevel();
521
		tblLimits.rows[lvl].cells[1].children[0].value = ae.GetLimitStorage(lvl) + 1;
522
		tblLimits.rows[lvl].cells[2].children[0].value = ae.GetLimitNormalA(lvl);
523
		tblLimits.rows[lvl].cells[3].children[0].value = ae.GetLimitShieldA(lvl);
524
	}
525
526
	// Accounts
527
	const tblAccs = document.getElementById("tbd_accs");
528
529
	// All: Our account
530
	const row = tblAccs.insertRow(-1);
531
	let cell;
532
	cell = row.insertCell(-1); cell.textContent = ae.GetUserPkHex();
533
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.GetTotalMsgBytes() / 1024 / 1024);
534
	cell = row.insertCell(-1); cell.textContent = ae.GetAddressCountNormal();
535
	cell = row.insertCell(-1); cell.textContent = ae.GetAddressCountShield();
536
	cell = row.insertCell(-1); cell.textContent = ae.GetUserLevel();
537
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\" disabled=\"disabled\">+</button>";
538
539
	cell = row.insertCell(-1); cell.innerHTML = "<button id=\"btn_downme\" type=\"button\" autocomplete=\"off\" disabled=\"disabled\">&minus;</button>";
540
	cell.children[0].onclick = function() {
541
		const newLevel = parseInt(row.cells[4].textContent) - 1;
542
		ae.Account_Update(ae.GetUserPkHex(), newLevel, function(success) {
543
			if (success) row.cells[4].textContent = newLevel;
544
		});
545
	};
546
547
	cell = row.insertCell(-1); cell.innerHTML = "<button id=\"btn_killme\" type=\"button\" autocomplete=\"off\" disabled=\"disabled\">X</button>";
548
	cell.children[0].onclick = function() {
549
		ae.Account_Delete(ae.GetUserPkHex(), function(success) {
550
			if (success) row.remove();
551
		});
552
	};
553
554
	document.getElementById("txt_reg").disabled = !ae.IsUserAdmin();
555
	document.getElementById("btn_reg").disabled = !ae.IsUserAdmin();
556
557
	// Contacts
558
	for (let i = 0; i < ae.GetContactCount(); i++) {
559
		addContact(
560
			ae.GetContactMail(i),
561
			ae.GetContactName(i),
562
			ae.GetContactNote(i)
563
		);
564
	}
565
566
	// Addresses
567
	for (let i = 0; i < ae.GetAddressCount(); i++) {
568
		addAddress(i);
569
	}
570
571
	updateAddressCounts();
572
	addMessages();
573
	addUploads();
574
	addSent();
575
}
576
577
function deleteAddress(addr) {
578
	let btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
579
	for (let i = 0; i < btns.length; i++) btns[i].disabled = true;
580
581
	let addressToDelete = -1;
582
583
	for (let i = 0; i < ae.GetAddressCount(); i++) {
584
		if (addr === ae.GetAddress(i)) {
585
			addressToDelete = i;
586
			break;
587
		}
588
	}
589
590
	if (addressToDelete === -1) return;
591
592
	ae.Address_Delete(addressToDelete, function(success) {
593
		if (success) {
594
			document.getElementById("tbl_addrs").deleteRow(addressToDelete);
595
			document.getElementById("write_from").remove(addressToDelete);
596
			updateAddressCounts();
597
598
			if (ae.GetAddressCountNormal() < ae.GetLimitNormalA(ae.GetUserLevel())) document.getElementById("btn_address_create_normal").disabled = false;
599
			if (ae.GetAddressCountShield() < ae.GetLimitShieldA(ae.GetUserLevel())) document.getElementById("btn_address_create_shield").disabled = false;
600
601
			ae.Private_Update(function(success2) {
602
				if (!success2) console.log("Failed to update the Private field");
603
604
				btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
605
				for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
606
			});
607
		} else {
608
			console.log("Failed to delete address");
609
610
			btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
611
			for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
612
		}
613
	});
614
}
615
616 View Code Duplication
function shieldMix(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
617
	let newAddr = "";
618
619
	for (let i = 0; i < 16; i++) {
620
		switch (addr.charAt(i)) {
621
			case '1':
622
				newAddr += "1iIlL".charAt(Math.floor(Math.random() * 5));
623
				break;
624
			case '0':
625
				newAddr += "0oO".charAt(Math.floor(Math.random() * 3));
626
				break;
627
			case 'w':
628
				newAddr += "VvWw".charAt(Math.floor(Math.random() * 4));
629
				break;
630
			default:
631
				newAddr += (Math.random() > 0.5) ? addr.charAt(i) : addr.charAt(i).toUpperCase();
632
		}
633
	}
634
635
	return newAddr;
636
}
637
638
function addAddress(num) {
639
	const addrTable = document.getElementById("tbl_addrs");
640
	const row = addrTable.insertRow(-1);
641
	const cellAddr = row.insertCell(-1);
642
	const cellChk1 = row.insertCell(-1);
643
	const cellChk2 = row.insertCell(-1);
644
	const cellChk3 = row.insertCell(-1);
645
	const cellBtnD = row.insertCell(-1);
646
647
	cellAddr.textContent = ae.GetAddress(num);
648
	cellAddr.onclick = function() {
649
		if (cellAddr.textContent.length === 16)
650
			navigator.clipboard.writeText(shieldMix(cellAddr.textContent) + "@" + ae.GetDomainEml());
1 ignored issue
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
651
		else
652
			navigator.clipboard.writeText(cellAddr.textContent + "@" + ae.GetDomainEml());
653
	};
654
655
	cellChk1.innerHTML = ae.GetAddressAccExt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
656
	cellChk2.innerHTML = ae.GetAddressAccInt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
657
	cellChk3.innerHTML = ae.GetAddressUse_Gk(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
658
659
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
660
	cellBtnD.onclick = function() {deleteAddress(cellAddr.textContent);};
661
662
	const opt = document.createElement("option");
663
	opt.value = cellAddr.textContent;
664
	opt.textContent = cellAddr.textContent + "@" + ae.GetDomainEml();
665
	document.getElementById("write_from").appendChild(opt);
666
}
667
668
document.getElementById("btn_dele").onclick = function() {
669
	this.blur();
670
671
	if (tab === TAB_WRITE) {
672
		tabs[tab].cur = 0;
673
		updateTab();
674
675
		document.getElementById("write_recv").value = "";
676
		document.getElementById("write_subj").value = "";
677
		document.getElementById("write_body").value = "";
678
679
		document.getElementById("write_recv").focus();
680
	}
681
};
682
683
document.getElementById("btn_updt").onclick = function() {
684
	const btn = this;
685
	btn.disabled = true;
686
	btn.blur();
687
688
	if (tab === TAB_INBOX) {
689
		document.getElementById("tbl_inbox").style.opacity = 0.5;
690
691
		ae.Message_Browse(true, false, function(successBrowse) {
692
			document.getElementById("tbl_inbox").style.opacity = 1;
693
694
			if (successBrowse) {
695
				addMessages();
696
				addUploads();
697
				btn.disabled = false;
698
			} else {
699
				console.log("Failed to refresh");
700
				btn.disabled = false;
701
			}
702
		});
703
	}
704
};
705
706
function addContact(mail, name, note) {
707
	const tbl = document.getElementById("tbl_ctact");
708
	const row = tbl.insertRow(-1);
709
	const cellMail = row.insertCell(-1);
710
	const cellName = row.insertCell(-1);
711
	const cellNote = row.insertCell(-1);
712
	const cellBtnD = row.insertCell(-1);
713
714
	cellMail.textContent = mail;
715
	cellName.textContent = name;
716
	cellNote.textContent = note;
717
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
718
719
	cellMail.contentEditable = true;
720
	cellName.contentEditable = true;
721
	cellNote.contentEditable = true;
722
723
	cellBtnD.onclick = function() {row.remove();};
724
}
725
726
document.getElementById("btn_newcontact").onclick = function() {
727
	addContact("", "", "");
728
};
729
730
document.getElementById("btn_savecontacts").onclick = function() {
731
	while (ae.GetContactCount() > 0) {
732
		ae.DeleteContact(0);
733
	}
734
735
	for (const row of document.getElementById("tbl_ctact").rows) {
736
		ae.AddContact(row.cells[0].textContent, row.cells[1].textContent, row.cells[2].textContent);
737
	}
738
739
	const btn = this;
740
	btn.disabled = true;
741
742
	ae.Private_Update(function(success) {
743
		btn.disabled = false;
744
745
		if (!success) {
746
			console.log("Failed contacts update");
747
		}
748
	});
749
};
750
751
function updateTab() {
752
	switch (tab) {
753
		case TAB_INBOX:
754
			addMessages();
755
		break;
756
757
		case TAB_DRBOX:
758
			addSent();
759
		break;
760
761
		case TAB_WRITE:
762
			switch (tabs[tab].cur) {
763
				case 0: // Write
764
					document.getElementById("div_write_1").hidden = false;
765
					document.getElementById("div_write_2").hidden = true;
766
					document.getElementById("write_body").focus();
767
				break;
768
769
				case 1: // Verify
770
					ae.Address_Lookup(document.getElementById("write_recv").value, function(pk) {
771
						if (pk) {
772
							document.getElementById("div_write_1").hidden = true;
773
							document.getElementById("div_write_2").hidden = false;
774
775
							document.getElementById("write2_from").textContent = document.getElementById("write_from").value + "@" + ae.GetDomainEml();
776
							document.getElementById("write2_recv").textContent = document.getElementById("write_recv").value;
777
							document.getElementById("write2_pkey").textContent = sodium.to_hex(pk);
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
778
779
							document.getElementById("write2_subj").textContent = document.getElementById("write_subj").value;
780
							document.getElementById("write2_rply").textContent = document.getElementById("write_rply").textContent;
781
							document.getElementById("write2_body").textContent = document.getElementById("write_body").value;
782
						} else {
783
							console.log("Failed lookup");
784
						}
785
					});
786
				break;
787
788
				case 2: // Send
789
					ae.Message_Create(
790
						document.getElementById("write_subj").value,
791
						document.getElementById("write_body").value,
792
						document.getElementById("write_from").value,
793
						document.getElementById("write_recv").value,
794
						document.getElementById("write_rply").textContent,
795
						(document.getElementById("write2_recv").textContent.indexOf("@") > 0) ? null : sodium.from_hex(document.getElementById("write2_pkey").textContent),
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
796
						function(success) {
797
							if (success) {
798
								console.log("Sent ok");
799
							} else {
800
								console.log("Failed sending");
801
							}
802
						}
803
					);
804
				break;
805
			}
806
		break;
807
808
		case TAB_NOTES:
809
			for (let i = 0; i <= tabs[tab].max; i++) {
810
				document.getElementById("div_notes").children[i].hidden = (i !== tabs[tab].cur);
811
			}
812
		break;
813
814
		case TAB_TOOLS:
815
			for (let i = 0; i <= tabs[tab].max; i++) {
816
				document.getElementById("div_tools").children[i].hidden = (i !== tabs[tab].cur);
817
			}
818
		break;
819
	}
820
821
	document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
822
	document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
823
}
824
825
document.getElementById("btn_left").onclick = function() {
826
	tabs[tab].cur--;
827
	if (tabs[tab].cur === 0) this.disabled = true;
828
	if (tabs[tab].cur < tabs[tab].max) document.getElementById("btn_rght").disabled = false;
829
	updateTab();
830
	this.blur();
831
};
832
833
document.getElementById("btn_rght").onclick = function() {
834
	tabs[tab].cur++;
835
	if (tabs[tab].cur === tabs[tab].max) this.disabled = true;
836
	document.getElementById("btn_left").disabled = false;
837
	updateTab();
838
	this.blur();
839
};
840
841
const buttons = document.querySelector("#main1 > .top").getElementsByTagName("button");
842
for (let i = 0; i < buttons.length; i++) {
843
	buttons[i].onclick = function() {
844
		tab = i;
845
846
		for (let j = 0; j < buttons.length; j++) {
847
			document.querySelector("#main1 > .mid").children[j].hidden = (tab !== j);
848
			buttons[j].disabled = (tab === j);
849
		}
850
851
		document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
0 ignored issues
show
Bug introduced by
The variable tab is changed as part of the for loop for example by i on line 844. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
852
		document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
853
		document.getElementById("btn_dele").disabled = !tabs[tab].btnDele;
854
		document.getElementById("btn_updt").disabled = !tabs[tab].btnUpdt;
855
	};
856
}
857
858
function addressCreate(addr) {
859
	const btnN = document.getElementById("btn_address_create_normal");
860
	const btnS = document.getElementById("btn_address_create_shield");
861
	btnN.disabled = true;
862
	btnS.disabled = true;
863
864
	ae.Address_Create(addr, function(success1) {
865
		if (success1) {
866
			ae.Private_Update(function(success2) {
867
				addAddress(ae.GetAddressCount() - 1);
868
				if (addr !== "SHIELD") document.getElementById("txt_address_create_normal").value = "";
869
				updateAddressCounts();
870
871
				if (!success2) console.log("Failed to update the Private field");
872
873
				if (ae.GetAddressCountNormal() < ae.GetLimitNormalA(ae.GetUserLevel())) btnN.disabled = false;
874
				if (ae.GetAddressCountShield() < ae.GetLimitShieldA(ae.GetUserLevel())) btnS.disabled = false;
875
			});
876
		} else {
877
			console.log("Failed to add address");
878
879
			if (ae.GetAddressCountNormal() < ae.GetLimitNormalA(ae.GetUserLevel())) btnN.disabled = false;
880
			if (ae.GetAddressCountShield() < ae.GetLimitShieldA(ae.GetUserLevel())) btnS.disabled = false;
881
		}
882
	});
883
}
884
885
document.getElementById("btn_address_create_normal").onclick = function() {
886
	if (ae.GetAddressCountNormal() >= ae.GetLimitNormalA(ae.GetUserLevel())) return;
887
888
	const txtNewAddr = document.getElementById("txt_address_create_normal");
889
	if (!txtNewAddr.reportValidity()) return;
890
891
	addressCreate(txtNewAddr.value);
892
};
893
894
document.getElementById("btn_address_create_shield").onclick = function() {
895
	if (ae.GetAddressCountShield() >= ae.GetLimitShieldA(ae.GetUserLevel())) return;
896
897
	addressCreate("SHIELD");
898
};
899
900
document.getElementById("btn_reg").onclick = function() {
901
	const btn = document.getElementById("btn_reg");
902
	const txt = document.getElementById("txt_reg");
903
	if (!txt.reportValidity()) return;
904
	btn.disabled = true;
905
906
	ae.Account_Create(txt.value, function(success) {
907
		if (success) {
908
			addAccountToTable(ae.Admin_GetUserCount() - 1);
909
			txt.value = "";
910
		}
911
912
		btn.disabled = false;
913
	});
914
};
915
916
document.getElementById("chk_downme").onclick = function() {document.getElementById("btn_downme").disabled = !this.checked;};
917
document.getElementById("chk_killme").onclick = function() {document.getElementById("btn_killme").disabled = !this.checked;};
918
919
document.getElementById("btn_notepad_saveupl").onclick = function() {
920
	const np = document.getElementById("txt_notepad");
921
	np.disabled = true;
922
923
	let fname = prompt("Save as...", "Untitled");
0 ignored issues
show
Debugging Code Best Practice introduced by
The prompt UI element is often considered obtrusive and is generally only used as a temporary measure. Consider replacing it with another UI element.
Loading history...
924
	if (!fname.endsWith(".txt")) fname += ".txt";
925
926
	ae.Message_Upload(fname, np.value, function(success) {
927
		if (success) {
928
			np.value = "";
929
			addUploads();
930
			document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.GetTotalMsgBytes() / 1024 / 1024);
931
		}
932
933
		console.log("Failed to add text");
934
		np.disabled = false;
935
	});
936
};
937
938
document.getElementById("btn_upload").onclick = function() {
939
	const btn = this;
940
	const fileSelector = document.createElement("input");
941
	fileSelector.type = "file";
942
	fileSelector.click();
943
944
	fileSelector.onchange = function() {
945
		btn.disabled = true;
946
947
		const reader = new FileReader();
1 ignored issue
show
Bug introduced by
The variable FileReader seems to be never declared. If this is a global, consider adding a /** global: FileReader */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
948
		reader.onload = function() {
949
			ae.Message_Upload(fileSelector.files[0].name, new Uint8Array(reader.result), function(success) {
950
				if (success) {
951
					addUploads();
952
					document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.GetTotalMsgBytes() / 1024 / 1024);
953
				} else {
954
					console.log("Failed upload");
955
				}
956
957
				btn.disabled = false;
958
			});
959
		};
960
961
		reader.readAsArrayBuffer(fileSelector.files[0]);
962
	};
963
};
964
965
document.getElementById("btn_pg").onclick = function() {
966
	localStorage.greeting = document.getElementById("txt_pg").value;
1 ignored issue
show
Bug introduced by
The variable localStorage seems to be never declared. If this is a global, consider adding a /** global: localStorage */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
967
};
968
969
document.getElementById("txt_skey").onkeyup = function(event) {
970
	if (event.key === "Enter") {
971
		event.preventDefault();
972
		document.getElementById("btn_enter").click();
973
	}
974
};
975
976
document.getElementById("btn_enter").onclick = function() {
977
	const txtSkey = document.getElementById("txt_skey");
978
	if (!txtSkey.reportValidity()) return;
979
980
	const btn = this;
981
	btn.disabled = true;
982
	document.getElementById("txt_skey").style.background = "#233";
983
984
	ae.SetKeys(txtSkey.value, function(successSetKeys) {
985
		if (successSetKeys) {
986
			ae.Message_Browse(false, true, function(successBrowse) {
987
				if (successBrowse) {
988
					txtSkey.value = "";
989
					document.getElementById("div_begin").hidden = true;
990
					document.getElementById("div_main").style.display = "grid";
991
					reloadAccount();
992
993
					if (ae.IsUserAdmin()) {
994
						ae.Account_Browse(function(successAcc) {
995
							if (successAcc) {for (let i = 0; i < ae.Admin_GetUserCount(); i++) {addAccountToTable(i);}}
996
							else console.log("Failed to Account_Browse");
997
						});
998
					}
999
				} else {
1000
					console.log("Failed to enter");
1001
					btn.disabled = false;
1002
					document.getElementById("txt_skey").style.background = "#466";
1003
					txtSkey.focus();
1004
				}
1005
			});
1006
		} else {
1007
			console.log("Invalid format for key");
1008
			btn.disabled = false;
1009
			document.getElementById("txt_skey").style.background = "#466";
1010
			txtSkey.focus();
1011
		}
1012
	});
1013
};
1014
1015
});
1016